查看原文
其他

【含源码+过程】深入剖析拉勾网,小白也来玩数据(二)

2017-12-17 韦艳莹 Python爱好者社区

作者:韦艳莹

知乎专栏:Python爬虫实战日记

https://zhuanlan.zhihu.com/Waking-up


前文传送门:

【用户案例】深度剖析拉勾网,小白也来玩数据


拉钩网爬虫的源码分析爬虫策略问题解决


拉钩网因其json格式的结构化数据,
成为几乎所有“爬者”必经的练手场

网上许多高手也分享了他们的经验和代码。

上一篇我们简单分析和展示了数据。
今天分几块来深入剖析拉钩网爬虫。


一、一般爬取策略


多说无益,以图为例,简要分析~





已经尽量解析的详细了,一般爬取思路大概就是这样。


二 、爬虫新思路


上面我们谈了一般思路,相信很多爬友早就发现了。然而拉勾网的爬虫实在太多了,其反爬机制经常变动,爬取难度逐渐增加


这一回我用上面的方法,结果返回这样:


懵了。
最初以为是user_agent等问题,又设随机数还是不见好。估计是拉钩修改了反爬机制


试着模拟登录,然而,Form采用复杂的
暗文密码,成功吓退小白。


最后重新构造URL,get方式解决


那我是怎么做到的呢?


最初是盯着network发呆,后面留意到URL后面的needAddtionalResult=false

'needAdditionalResult',额外添加?好吧,那就随便加点东西。加什么好呢?





那就随便这个好咯,然后返回这样





直接构造URL,哈哈我简直聪明~ (^_^)!
纯属瞎撞,第二天想到onenote中一笔记:





我们用form提交的表单,其实最终会变成上面那样的格式。(用不用post基本差不多)

get方式获取数据,加个cookies即可。(后面才知道这个叫 用Cookies模拟登录
代码如下,还是放个完整版:

#!/usr/bin/env python #-*-coding:utf-8 -*- __author__='WYY' __date__='2017.03.29' #实战小项目:爬取拉钩网并作小型数据分析 import requests import json import xlwt import time import random class Spider():    def __init__(self):        self.keyword=raw_input(u'请输入职位:')    #获取数据    def getData(self,url):        user_agents=['Mozilla/5.0 (Windows NT 6.1; WOW64; rv:23.0) Gecko/20130406 Firefox/23.0',                   'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0',                   'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/533+ \(KHTML, like Gecko) Element Browser 5.0',                   'IBM WebExplorer /v0.94', 'Galaxy/1.0 [en] (Mac OS X 10.5.6; U; en)',                   'Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; WOW64; Trident/6.0)',                   'Opera/9.80 (Windows NT 6.0) Presto/2.12.388 Version/12.14',                   'Mozilla/5.0 (iPad; CPU OS 6_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) \Version/6.0 Mobile/10A5355d Safari/8536.25',                   'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) \Chrome/28.0.1468.0 Safari/537.36',                   'Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.0; Trident/5.0; TheWorld)']        index=random.randint(0, 9)        user_agent=user_agents[index]        headers={'User_agent':user_agent,             'cookie':'your cookies'} #cookie要自己抓        html=requests.get(url,headers=headers)        data=json.loads(html.text)        return data    #获取职位信息并存入列表    def getPosition(self,url):        data=self.getData(url)        position=data['content']['positionResult']['result']        po_list=[]        if position is not None:            for i in position:                main=[]                main.append(i['companyFullName'])                main.append(i['financeStage'])                main.append(i['positionName'])                main.append(i['positionLables'])                main.append(i['salary'])                main.append(i['city'])                main.append(i['education'])                main.append(i['workYear'])                main.append(i['jobNature'])                main.append(i['createTime'])                po_list.append(main)        return po_list    #获取数据,存入一个大的list    def saveDetail(self):        self.New=int(raw_input(u'请输入要爬取的页数:'))        self.time=time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())        print u'\n本地时间:',self.time        print u'\n开始采集数据...'        container=[]        for page in range(1,self.New+1):            self.url='https://www.lagou.com/jobs/positionAjax.json?px=new&first=true&pn='+str(page)+'&kd='+str(self.keyword)            po_list=self.getPosition(self.url)            time.sleep(3)            print u'第',page,u'项完毕'            container=container+po_list        return container    #将数据存入excel    def saveAll(self):        book=xlwt.Workbook()        sheet =book.add_sheet(str(self.keyword), cell_overwrite_ok=True)        container=self.saveDetail()        print u'\n采集完毕'        print u'\n准备将数据存入表格...'        heads=[u'公司全名', u'融资状况', u'工作名称', u'标签', u'薪酬', u'城市', u'学历要求',u'经验要求',u'工作类型',u'数据创建时间']        ii=0        for head in heads:            sheet.write(0,ii,head)            ii+=1        i=1        for list in container:            j=0            for one in list:                sheet.write(i, j, one)                j+=1            i+=1        book.save(str(self.keyword)+'.xls')        print u'\n录入成功!' spider=Spider() spider.saveAll()


有盆友可能会问了:随便设个New简单,
可怎么获得最大页数呀


好吧,我坦白:手动试出来的
(先大概定个范围,每次取中间数,试个5、6次就出来了,也简单)


其实我也想过用个if position==[]或者if position=None就break结束循环,可却不知道为什么行不通,真是怪了。可是如果先遍历获取最大页数,后面又得遍历一次,抓取次数多了,难保不被网站发现被封IP。
只好这样了(这里有待改进)。


可以看到,整个爬取过程仅用request、json、xlwt等几个关键库。

总结爬虫新思路:


直接pn构造URL实现翻页,加上cookies伪装浏览器,用get方式获取

是不是hin简单^_^


三、突破IP限制


爬虫爬到一半时,又出了幺蛾子





再上去一看




原来IP被封 了,难怪。

(这样的情况还是第一次)


查了一下,网上有说可以用代理池。
可又得设计爬虫抓代理,不免麻烦。
后面想到之前爬图片网站时,注册的vpn。


vpn不就是代理么,还可各种线路随便切换,哈哈哈我简直聪明~ (^_^)!

查了一点资料,有关反反爬及突破IP限制,


总结几个方法:
1、设置代理池(可以网上抓代理,不过稳定性是问题)
2、使用vpn(原理同上)
3、分布式抓取(这个我也没学到>_<)
4、设置等待时间,放慢抓取速度
5、修改请求头( user_agent、cookies)
6、模拟登录

当然,最有效当属123


四、数据分析 — 一些感悟


工具用的BDP(奇妙的分析软件)。
词云用的标签一栏,直接丢BDP自动生成。
后面发现有欠妥当,因为有些数据标签那一块什么都没有。

对几个维度进行了粗略分析,效果还不错,比如这样





细心的盆友可能又发现了,怎么没有C# ?
其实,我也想的。。。

如图所示搜C#时,会搜出许多C\C++的内容,乱而麻烦,只好舍弃。

第一次亲自参与3万多数据的分析,新鲜。后面一想,其实爬虫程序不过只是个采集数据的手段(或者说工具)。

关键还是 具体的数据分析以及应用转化 单单抓个几十万烂在excel表里,没有任何意义。


五、源码剖析 — 新发现


爬过拉钩的朋友肯定会发现一个现象:打开一个页面,过一阵子再重新打开
发现不再是原来页面了,变成了别的


可是真的是这样么?


放几个图





get到了么?
只是顺序变了下,内容是不变的

换汤不换药,特么全是 障眼法 啊!!!
难为了拉钩的前端工程师 [摊手]

看来也只有我这种 既无聊又聪明又有耐心的人才会发现了




这个小项目我也放到了github上了:

github.com/LUCY78765580

(如果您觉得不错,可顺便在Github上给个star哦~)


最后总结本篇 几个要点

1、拉钩爬虫一般方法:Post模拟浏览器
2、新思路:get方式+cookies伪装,
直接pn构建URL实现翻页和遍历
3、突破IP限制(各种方法)
4、程序不过工具,关键策略、数据分析
5、源码剖析新发现:页面原来障眼法


对得起这个"深入剖析"的标题,小白已经尽她最大的努力啦~

(学习爬虫才一月左右,文章可能有不足之处,个中出入还请各位大神多多指正)

本篇就是这样啦~

Python爱好者社区历史文章大合集

Python爱好者社区历史文章列表(每周append更新一次)

福利:文末扫码立刻关注公众号,“Python爱好者社区”,开始学习Python课程:

关注后在公众号内回复“课程”即可获取:

0.小编的Python入门视频课程!!!

1.崔老师爬虫实战案例免费学习视频。

2.丘老师数据科学入门指导免费学习视频。

3.陈老师数据分析报告制作免费学习视频。

4.玩转大数据分析!Spark2.X+Python 精华实战课程免费学习视频。

5.丘老师Python网络爬虫实战免费学习视频。


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存